﻿import D3D.Vertex;
/**   矩阵类(各种变形\投影等)
*
* @author  Tophy
* @version 1.0
* @since
*/
class D3D.Matrix
{
	// 属性
	private var me : Object;
	private var PT : Array;
	/*   矩阵数据
	*	|xx,yx,zx,wx|
	*	|xy,yy,zy,wy|
	*	|xz,yz,zz,wz|
	*	|xw,yw,zw,s |
	*/
	public var xx, xy, xz, xw, yx, yy, yz, yw, zx, zy, zz, zw, wx, wy, wz, s : Number;
	// 透视比率
	public var _zf : Number;
	/**构造函数
	*
	* @usage
	* @param   _zf 透视比率  0 或 不填默认为无透视效果
	* @return
	*/
	public function Matrix (obj : Object)
	{
		init (obj);
	};
	/** init函数 默认为无透视效果
	*
	* @usage
	* @param   obj 矩阵 参考上面
	* @return
	*/
	private function init (obj)
	{
		//Debug.traceAllObj(obj)
		if (obj == undefined)
		{
			//无变换矩阵
			xx = 1;
			xy = 0;
			xz = 0;
			xw = 0;
			yx = 0;
			yy = 1;
			yz = 0;
			yw = 0;
			zx = 0;
			zy = 0;
			zz = 1;
			zw = 0;
			wx = 0;
			wy = 0;
			wz = 0;
			s = 1;
		} else
		{
			xx = (obj.xx != undefined) ? ((obj.xx.toString () != "NaN") ? Number (obj.xx) : 1) : 1;
			xy = (obj.xy != undefined) ? ((obj.xy.toString () != "NaN") ? Number (obj.xy) : 0) : 0;
			xz = (obj.xz != undefined) ? ((obj.xz.toString () != "NaN") ? Number (obj.xz) : 0) : 0;
			xw = (obj.xw != undefined) ? ((obj.xw.toString () != "NaN") ? Number (obj.xw) : 0) : 0;
			yx = (obj.yx != undefined) ? ((obj.yx.toString () != "NaN") ? Number (obj.yx) : 0) : 0;
			yy = (obj.yy != undefined) ? ((obj.yy.toString () != "NaN") ? Number (obj.yy) : 1) : 1;
			yz = (obj.yz != undefined) ? ((obj.yz.toString () != "NaN") ? Number (obj.yz) : 0) : 0;
			yw = (obj.yw != undefined) ? ((obj.yw.toString () != "NaN") ? Number (obj.yw) : 0) : 0;
			zx = (obj.zx != undefined) ? ((obj.zx.toString () != "NaN") ? Number (obj.zx) : 0) : 0;
			zy = (obj.zy != undefined) ? ((obj.zy.toString () != "NaN") ? Number (obj.zy) : 0) : 0;
			zz = (obj.zz != undefined) ? ((obj.zz.toString () != "NaN") ? Number (obj.zz) : 1) : 1;
			zw = (obj.zw != undefined) ? ((obj.zw.toString () != "NaN") ? Number (obj.zw) : 0) : 0;
			wx = (obj.wx != undefined) ? ((obj.wx.toString () != "NaN") ? Number (obj.wx) : 0) : 0;
			wy = (obj.wy != undefined) ? ((obj.wy.toString () != "NaN") ? Number (obj.wy) : 0) : 0;
			wz = (obj.wz != undefined) ? ((obj.wz.toString () != "NaN") ? Number (obj.wz) : 0) : 0;
			s = (obj.s != undefined) ? ((obj.s.toString () != "NaN") ? Number (obj.s) : 1) : 1;
		}
		me = this;
		//me.toString ();
	}
	/**  获取旋转变换阵区
	*
	* @usage
	* @param   x  绕X轴角度
	* @param   y 绕y轴角度
	* @param   z 绕z轴角度
	* @param   m 所在变换矩阵
	* @return
	*/
	public static function getRotationMatrix (x, y, z, m : Matrix) : Matrix
	{
		if (x == undefined || y == undefined || z == undefined)
		{
			say ("获取旋转变换阵区出错.");
			return null;
		}
		var sinX = Math.sin (x);
		var sinY = Math.sin (y);
		var sinZ = Math.sin (z);
		var cosX = Math.cos (x);
		var cosY = Math.cos (y);
		var cosZ = Math.cos (z);
		var oo : Object = new Object ();
		oo.xx = cosY * cosZ;
		oo.xy = sinX * sinY * cosZ - cosX * sinZ;
		oo.xz = cosX * sinY * cosZ + sinX * sinZ;
		oo.yx = cosY * sinZ;
		oo.yy = cosX * cosZ - sinX * sinY * sinZ;
		oo.yz = - cosX * sinY * sinZ - sinX * cosZ;
		oo.zx = - sinY;
		oo.zy = sinX * cosY;
		oo.zz = cosX * cosY;
		var mm : Matrix = new Matrix (oo);
		if (m.xx != undefined)
		{
			trace("??");
			mm=mm.matrixX (m);
		}
		//mm.toString();
		return mm;
	}
	/**  旋转
	*
	* @usage
	* @param   v Vertex类型数组 或点
	* @param   x null 或 弧度
	* @param   y null 或 弧度
	* @param   z null 或 弧度
	* @param   mm 变换矩阵 Matrix类型(可不填)
	* @return
	*/
	public function zRotation (v, x, y, z, mm)
	{
		var vv = Rotation (v, x, y, z, mm);
		if (vv == null)
		{
			return null;
		}
		vv = zeroW (vv);
		return vv;
	}
	public function Rotation (v, x, y, z, mm)
	{
		if (v != undefined && mm.xx == undefined)
		{
			mm = Matrix.getRotationMatrix (x, y, z);
			//mm.toString();
		}
		if (v [0].x != undefined)
		{
			var a : Array = new Array ();
			var i = 0;
			while (i < v.length)
			{
				a.push (me.Rotation (v [i] , x, y, z, mm));
				i ++;
			}
			return a;
		} else if (v.x != undefined)
		{
			v = matrixChen (mm, v);
			return v;
		}
	}
	/** 移动
	*
	* @usage
	* @param   v  Vertex类型数组 或数据
	* @param   x  X方向移动数量
	* @param   y  Y方向移动数量
	* @param   z  Z方向移动数量
	* @param   mm 变换矩阵 Matrix(可不填)
	* @return
	*/
	public function zMove (v, x, y, z, mm)
	{
		var vv = Move (v, x, y, z, mm);
		if (vv == null)
		{
			return null;
		}
		vv = zeroW (vv);
		return vv;
	}
	public function Move (v, x, y, z, mm)
	{
		if (v != undefined && mm == undefined)
		{
			var oo : Object = new Object ();
			oo.xw = x;
			oo.yw = y;
			oo.zw = z;
			mm = new Matrix (oo);
		}
		if (v [0].x != undefined)
		{
			var a : Array = new Array ();
			var i = 0;
			while (i < v.length)
			{
				a.push (me.Move (v [i] , x, y, z, mm));
				i ++;
			}
			return a;
		} else if (v.x != undefined)
		{
			v = matrixChen (mm, v);
			return v;
		}
	}
	/**  透视投影变换()
	*
	* @usage
	* @param   v  Vertex类型数组 或数据
	* @param   zf 透视比率
	* @param   mm
	* @return
	*/
	public function zProject (v, zf, mm)
	{
		var vv = Project (v, zf, mm);
		if (vv == null)
		{
			return null;
		}
		vv = zeroW (vv);
		return vv;
	}
	public function Project (v, zf, mm)
	{
		if (v != undefined && mm == undefined)
		{
			var oo : Object = new Object ();
			oo.wz = zf;
			mm = new Matrix (oo);
		}
		if (v [0].x != undefined)
		{
			var a : Array = new Array ();
			var i = 0;
			while (i < v.length)
			{
				a.push (me.Project (v [i] , zf, mm));
				i ++;
			}
			return a;
		} else if (v.x != undefined)
		{
			v = matrixChen (mm, v);
			return v;
		}
	}
	/**     归一化
	*
	* @usage
	* @param   v 点 Vertex类型
	* @return
	*/
	public function zeroW (v)
	{
		if (v != undefined)
		{
			if (v [0].x != undefined)
			{
				var a : Array = new Array ();
				var i = 0;
				while (i < v.length)
				{
					a.push (me.zeroW (v [i]));
					i ++;
				}
				return a;
			} else if (v.x != undefined)
			{
				var rv : Vertex = new Vertex (v.x / v.w, v.y / v.w, v.z / v.w);
				return rv;
			} else
			{
				say ("参数不正确" + v.toString ());
				return null;
			}
		} else
		{
			say ("参数不正确" + v.toString ());
			return null;
		}
	}
	public function matrixX (m : Matrix ) : Matrix
	{
		var rt : Object = new Object ();
		rt.xx = (me.xx * m.xx + me.yx * m.xy + me.zx * m.xz + me.wx * m.xw);
		rt.yx = (me.xx * m.yx + me.yx * m.yy + me.zx * m.yz + me.wx * m.yw);
		rt.zx = (me.xx * m.zx + me.yx * m.zy + me.zx * m.zz + me.wx * m.zw);
		rt.wx = (me.xx * m.wx + me.yx * m.wy + me.zx * m.wz + me.wx * m.s);
		rt.xy = (me.xy * m.xx + me.yy * m.xy + me.zy * m.xz + me.wy * m.xw);
		rt.yy = (me.xy * m.yx + me.yy * m.yy + me.zy * m.yz + me.wy * m.yw);
		rt.zy = (me.xy * m.zx + me.yy * m.zy + me.zy * m.zz + me.wy * m.zw);
		rt.wy = (me.xy * m.wx + me.yy * m.wy + me.zy * m.wz + me.wy * m.s);
		rt.xz = (me.xz * m.xx + me.yz * m.xy + me.zz * m.xz + me.wz * m.xw);
		rt.yz = (me.xz * m.yx + me.yz * m.yy + me.zz * m.yz + me.wz * m.yw);
		rt.zz = (me.xz * m.zx + me.yz * m.zy + me.zz * m.zz + me.wz * m.zw);
		rt.wz = (me.xz * m.wx + me.yz * m.wy + me.zz * m.wz + me.wz * m.s);
		rt.xw = (me.xw * m.xx + me.yw * m.xy + me.zw * m.xz + me.s * m.xw);
		rt.yw = (me.xw * m.yx + me.yw * m.yy + me.zw * m.yz + me.s * m.yw);
		rt.zw = (me.xw * m.zx + me.yw * m.zy + me.zw * m.zz + me.s * m.zw);
		rt.s = (me.xw * m.wx + me.yw * m.wy + me.zw * m.wz + me.s * m.s);
		var rm : Matrix = new Matrix (rt);
		return rm;
	}
	/** 矩阵乘法运算
	*
	* @usage
	* @param   m1 变换矩阵
	* @param   x  Vertex类型数据 或 Vertex数组 或 X值
	* @param   y  Y值
	* @param   z  Z值
	* @param   w  W值
	* @return
	*/
	private function matrixChen (m1, x, y, z, w)
	{
		if (m1 == undefined)
		{
			say ("变换矩阵不正常.");
			return null;
		} else
		{
			//m1.toString ();
		}
		if (x [0] != undefined)
		{
			var a : Array = new Array ();
			var i = 0;
			while (i < x.length)
			{
				a.push (me.matrixChen (m1, x [i]));
				i ++;
			}
			return a;
		} else if (x.x != undefined)
		{
			return me.matrixChen (m1, x.x, x.y, x.z, x.w);
		} else
		{
			var xxx = (x * m1.xx + y * m1.xy + z * m1.xz + w * m1.xw);
			var yyy = (x * m1.yx + y * m1.yy + z * m1.yz + w * m1.yw);
			var zzz = (x * m1.zx + y * m1.zy + z * m1.zz + w * m1.zw);
			var www = (x * m1.wx + y * m1.wy + z * m1.wz + w * m1.s);
			return (new Vertex (xxx, yyy, zzz, www));
		}
	}
	public function toString ()
	{
		trace ("\r------ Matrix ------");
		trace ("  |" + xx + "," + yx + "," + zx + "," + wx + "|");
		trace ("  |" + xy + "," + yy + "," + zy + "," + wy + "|");
		trace ("  |" + xz + "," + yz + "," + zz + "," + wz + "|");
		trace ("  |" + xw + "," + yw + "," + zw + "," + s + "|");
		trace ("--------------------");
	}
	/** 消息输出
	*
	* @usage
	* @return
	*/
	private static function say (o)
	{
		trace ("Matrix:" + o);
	}
	//GET SET 函数
	public function get scale () : Number
	{
		return _zf;
	}
	public function set scale (zf : Number)
	{
		if (zf.toString () != NaN && zf != undefined)
		{
			_zf = zf;
		}
	}
}
